package com.bluepocket.gao.events;

import java.util.HashSet;

/**
 * Helper for building observers/notifiers. This is
 * {@link java.beans.PropertyChangeSupport} rewrite to work with GWT.<br>
 * To develop a notifier you have to instantiate this class and expose delegate
 * methods to (un)register {@link PropertyChangeListener}. Notifier calls
 * {@link PropertyChangeSupport#propertyChanged(Object, Object)} to send a
 * notification. <br>
 * <h3>Example</h3>
 * 
 * <pre>
 * class Notifier {
 * 	private final PropertyChangeSupport&lt;Notifier, String&gt; pcs;
 * 
 * 	public MyComposite() {
 * 		pcs = new PropertyChangeSupport&lt;Notifier, String&gt;();
 * 	}
 * 
 * public void doNotification(){
 *     pcs.propertyChanged(this,&quot;String value&quot;);
 * }
 * 
 * 	public void addPropertyChangeListener(
 * 			PropertyChangeListener&lt;Notifier, String&gt; listener) {
 * 		pcs.addPropertyChangeListener(listener);
 * 	}
 * 
 * 	public void removePropertyChangeListener(
 * 			PropertyChangeListener&lt;Notifier, String&gt; listener) {
 * 		pcs.removePropertyChangeListener(listener);
 * 	}
 * }
 * 
 * class Observer {
 *     ...
 *     Notifier n = ...;
 *     PropertyChangeListener&lt;Notifier,String&gt; listener=new PropertyChangeListener&lt;Notifier,String&gt;(){
 *         public void propertyChanged(Notifier sender, String newValue){
 *             // serve the notification
 *             System.out.println(newValue);
 *         }
 *     } 
 *     n.addPropertyChangeListener(listener);
 *     ...
 * }
 * </pre>
 * 
 * @author Marcin Maciukiewicz (mm@bluepocket.com)
 * 
 * @param <T>Notifications sender type.
 * @param <R>The notification type.
 * @see java.beans.PropertyChangeSupport
 * @see PropertyChangeListener
 */
public class PropertyChangeSupport<T, R> {
	private final HashSet<PropertyChangeListener<T, R>> listeners;

	public PropertyChangeSupport() {
		listeners = new HashSet<PropertyChangeListener<T, R>>();
	}

	public void addPropertyChangeListener(PropertyChangeListener<T, R> listener) {
		if (listener == null) {
			throw new NullPointerException("Listener is null.");
		}
		listeners.add(listener);
	}

	public void removePropertyChangeListener(
			PropertyChangeListener<T, R> listener) {
		if (listener == null) {
			throw new NullPointerException("Listener is null.");
		}
		listeners.remove(listener);
	}

	public void propertyChanged(T sender, R value) {
		for (PropertyChangeListener<T, R> listener : listeners) {
			listener.propertyChanged(sender, value);
		}
	}
}
